﻿#include "flowingRayButton.h"
// 流动光线按钮
FlowingRayButton::FlowingRayButton(QWidget *parent)
    : QFrame(parent)
{
    border_radius=10;
    border=5;
    initUI();
}

FlowingRayButton::~FlowingRayButton()
{

}

void FlowingRayButton::initUI()
{
    this->resize(300, 100);
    this->setStyleSheet("QFrame{"
                  "	background-color: rgba(255, 255, 255,0);"
                  "	border:none;"
                  "	border-radius:10px;"
                  " Rborder-width:5px;"
                  "}"
                  "QPushButton{border-radius: 5px;color:#ff0066;}"
                  );
    m_pPushButton = new QPushButton(this);
    setBorder();

    QFont font;
    font.setPointSize(25);

    m_pPushButton->setFont(font);
    m_pPushButton->setText("Start Coding");
    m_pTimer = new QTimer(this);
    m_pTimer->setInterval(10);      //间隔毫秒
    connect(m_pTimer, SIGNAL(timeout()), this, SLOT(offsetUpdate()));
    initAnimationConfig();
}

void FlowingRayButton::setBorder(int border)
{
    int btn_width = this->width() - border * 2;
    int btn_height = this->height() - border * 2;
    int btn_x = border;
    int btn_y = border;
    m_pPushButton->setGeometry(QRect(btn_x, btn_y, btn_width, btn_height));
}

 // 根据样式重新配置(解析样式设置)
void FlowingRayButton::setStyleSheetConfig()
{
    /*匹配规则;
     * 注意：正则表达式在找到第一个匹配项后就会停止查找，所以它不会再次匹配。
     * 从头开始查找匹配 border-radius: 的部分，然后尝试匹配一个或多个数字字符 (\\d+)，而后匹配 px;
     * 使用 \\s* 来匹配可能存在的空格字符，包括零个或多个空格;
     * \\d+表示匹配一个或多个数字字符
     * 使用 (?P<border_radius>\\d+) 来匹配 border-radius 后面的数字，并将其命名为 border_radius;*/
    QRegularExpression radius_match("border-radius:\\s*(?P<border_radius>\\d+)px;");
    QRegularExpressionMatch radius_result = radius_match.match(this->styleSheet());
    if (radius_result.hasMatch())
    {
        //提取捕获组中命名为 border_radius的内容
        border_radius = radius_result.captured("border_radius").toInt();
    }

    QRegularExpression Rborder_width_match("Rborder-width:\\s*(?P<Rborder_width>\\d+)px;");
    QRegularExpressionMatch Rborder_width_result = Rborder_width_match.match(this->styleSheet());
    if (Rborder_width_result.hasMatch()) {
        border = Rborder_width_result.captured("Rborder_width").toInt();
    }

    // 根据样式重新配置QPushButton边界
    setBorder(border);
    initAnimationConfig();
}

// 初始化动画配置
void FlowingRayButton::initAnimationConfig()
{
    rect_1_offset = 0;
    rect_2_offset = 0;
    rect_1_start = 0;
    rect_2_start = -this->width();
    init_x = -this->width();
    flag = 0;
}

// 偏移更新
void  FlowingRayButton::offsetUpdate()
{
    if(rect_1_offset >= this->width()&&flag==0) {
        rect_1_offset = 0;
        rect_1_start = init_x;
        flag=1;
    }
    if(rect_1_offset >= this->width()*2&&flag==1) {
        rect_1_offset = 0;
        rect_1_start = init_x;
    }

    if (rect_2_offset >= this->width() * 2) {
        rect_2_offset = 0;
        rect_2_start = init_x;
    }

    rect_1_offset += 3;
    rect_2_offset += 3;

    update();
}

//重写处理鼠标光标进入部件的事件
void FlowingRayButton::enterEvent(QEvent *event)
{
    m_pTimer->start();
    // 调用父类的 enterEvent 函数，以保持默认行为
    QFrame::enterEvent(event);
}

//重写处理鼠标光标离开部件的事件
void FlowingRayButton::leaveEvent(QEvent *event)
{
    m_pTimer->stop();
    // 调用父类的 leaveEvent 函数，以保持默认行为
    QFrame::leaveEvent(event);
}

//重写绘制事件
void FlowingRayButton::paintEvent(QPaintEvent *event)
{
    // 调用父类的 paintEvent 函数，以保持默认行为
    QFrame::paintEvent(event);

    QPainterPath path;
    //添加一个带有圆角的矩形路径
    path.addRoundedRect(0, 0, this->width(), this->height(), border_radius, border_radius);

    QPainter painter(this);
    //设置渲染提示; QPainter::Antialiasing 是一种渲染提示，用于抗锯齿绘制，使得图形边缘更加平滑
    painter.setRenderHint(QPainter::Antialiasing);
    //设置画笔; Qt::NoPen 表示不使用画笔，也就是不绘制边框
    painter.setPen(Qt::NoPen);
    //设置剪裁路径，即限制绘制区域为指定的路径范围内
    painter.setClipPath(path);

    //线性渐变
    QLinearGradient gradient_1(rect_1_start + rect_1_offset, 0, rect_1_start + rect_1_offset + this->width(), 0);
    //在(0,1)之间设置颜色的渐变过程，将一个颜色逐渐过渡到另一个
    gradient_1.setColorAt(0, QColor(0, 164, 128, 230));
    gradient_1.setColorAt(0.166, QColor(13, 88, 166, 230));
    gradient_1.setColorAt(0.333, QColor(118, 8, 170, 230));
    gradient_1.setColorAt(0.5, QColor(255, 144, 0, 230));
    gradient_1.setColorAt(0.666, QColor(255, 255, 0, 230));
    gradient_1.setColorAt(0.833, QColor(165, 239, 0, 230));
    gradient_1.setColorAt(1, QColor(83, 223, 0, 230));

    painter.setBrush(gradient_1);
    painter.drawRect(rect_1_start + rect_1_offset, 0, this->width(), this->height());

    QLinearGradient gradient_2(rect_2_start + rect_2_offset, 0,rect_2_start + rect_2_offset + this->width(), 0);
    gradient_2.setColorAt(0, QColor(0, 164, 128, 230));
    gradient_2.setColorAt(0.166, QColor(13, 88, 166, 230));
    gradient_2.setColorAt(0.333, QColor(118, 8, 170, 230));
    gradient_2.setColorAt(0.5, QColor(255, 144, 0, 230));
    gradient_2.setColorAt(0.666, QColor(255, 255, 0, 230));
    gradient_2.setColorAt(0.833, QColor(165, 239, 0, 230));
    gradient_2.setColorAt(1, QColor(83, 223, 0, 230));

    painter.setBrush(gradient_2);
    painter.drawRect(rect_2_start + rect_2_offset, 0, this->width(), this->height());

}

QPushButton *FlowingRayButton::getFlowingRayButton()
{
    return m_pPushButton;
}
